﻿using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Windows.Forms;
using CommonEntity.CommonImageEntities;
using OpenCvSharp;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using ScienceAIApp.Helpers;
using ScienceAppService.Entities;
using ScienceAppService.ModuleInterface;
using ScienceAppService.Utils;
using Point = System.Windows.Point;

namespace ScienceAIApp.ViewModels;
public class ImageMarkDrawViewModel : ScienceBaseViewModel
{
    private bool _noFrush;
    private readonly IImageShowService _imageShowService;
    private readonly IMarkDrawService _markDrawService;
    private ImageOrientationEnum _currentImageOrientation;
    private double[] _preDrawP;

    public ReactiveCommand<int, Unit> GotoIndexCommand { get; }

    [Reactive] public Mat? OriginMat { get; set; }
    [Reactive] public Mat? LableMat { get; set; }
    [Reactive] public Mat? MarkMat { get; set; }
    [Reactive] public Mat? CrossLineMat { get; set; }
    [Reactive] public Mat? TagMat { get; set; }
    [Reactive] public int CurrentIndex { get; set; }
    [Reactive] public int Count { get; set; }
    [Reactive] public bool IsZoomOut { get; set; }

    public ReactiveCommand<Point, Unit> ImageMouseDownCommand { get; }

    public ReactiveCommand<int, Unit> MouseWheelUpdateCurrentIndexCommand { get; }

    /// <summary>
    /// 放大缩小
    /// </summary>
    public ReactiveCommand<bool, Unit> ZoomInOutCommand { get; }

    /// <summary>
    /// 放大缩小
    /// </summary>
    public Interaction<bool, Unit>? ZoomInOutInteraction { get; set; }

    /// <summary>
    /// 十字线事件
    /// </summary>
    public Interaction<double[], Unit> CrossLineInteraction { get; set; }

    /// <summary>
    /// 十字线
    /// </summary>
    public ReactiveCommand<Point, Unit> ImageLeftDownMoveCommand { get; }

    public ImageMarkDrawViewModel(IImageShowService imageShowService, IMarkDrawService markDrawService)
    {
        _imageShowService = imageShowService;
        _markDrawService = markDrawService;
        _currentImageOrientation = ImageOrientationEnum.None;
        Count = 0;
        CurrentIndex = 0;
        _preDrawP = new[] { 0.0, 0.0, 0.0 };

        // 放大缩小
        ZoomInOutInteraction = new Interaction<bool, Unit>();
        ZoomInOutCommand = ReactiveCommand.CreateFromTask<bool>(async flag =>
        {
            RxApp.MainThreadScheduler.Schedule(() =>
            {
                IsZoomOut = flag;
            });
            await ZoomInOutInteraction!.Handle(flag);
        });

        // 图像滚轮滑动触发
        GotoIndexCommand = ReactiveCommand.CreateFromTask<int>(async
            index =>
        {
            if (_noFrush || Count < 1) return;
            if (index < 0) index = 0;
            if (index > Count) index = Count;
            if (index != CurrentIndex)
                await _imageShowService.FrushMats(index, _currentImageOrientation);
        });

        // 十字线刷新获取，获取定位点ct值
        CrossLineInteraction = new Interaction<double[], Unit>();

        // 按下鼠标左键移动 -- 这里有十字线，todo 有绘制逻辑
        ImageLeftDownMoveCommand = ReactiveCommand.CreateFromTask<Point>(async p =>
        {
            if (OriginMat == null) return;
            if (p.X < 0 || p.X > 1024 || p.Y < 0 || p.Y > 1024) return;
            

            if (_markDrawService.CurrentMarkDrawType == SegToolsEnum.CrossLine)
            {
                var rsP = CalcPoint(p);
                if (rsP.All(i => i == -1)) return;
                await CrossLineInteraction!.Handle(rsP);
            }

            // 绘制逻辑
            if (_markDrawService.CurrentMarkDrawType.ToString().ToLower().Contains("draw") &&
                !_markDrawService.CurrentMarkDrawType.ToString().ToLower().Contains("drawnone"))
            {
                var rsP = CalcPoint(p, true);
                if (rsP.All(i => i == -1)) return;

                if (Math.Abs(_preDrawP[0] - rsP[0]) < 2 && Math.Abs(_preDrawP[1] - rsP[1]) < 2 &&
                    Math.Abs(_preDrawP[2] - rsP[2]) < 2)
                {
                    return;
                }

                _preDrawP = rsP;

                LableMat ??= AppCvUtil.CreateLableMat(OriginMat);
                LableMat = _markDrawService.Draw(rsP, LableMat!, _currentImageOrientation);
            }

            if (_markDrawService.CurrentMarkDrawType == SegToolsEnum.Erase)
            {
                var rsP = CalcPoint(p, true);
                if (rsP.All(i => i == -1)) return;

                if (Math.Abs(_preDrawP[0] - rsP[0]) < 2 && Math.Abs(_preDrawP[1] - rsP[1]) < 2 &&
                    Math.Abs(_preDrawP[2] - rsP[2]) < 2)
                {
                    return;
                }

                _preDrawP = rsP;

                LableMat ??= AppCvUtil.CreateLableMat(OriginMat);
                LableMat = _markDrawService.Draw(rsP, LableMat!, _currentImageOrientation,true);
            }

        });

        // 图像标记事件
        ImageMouseDownCommand = ReactiveCommand.CreateFromTask<Point>(async
            p =>
        {
            if (OriginMat == null || _markDrawService.CurrentMarkDrawType.ToString().ToLower().Contains("draw")
                || _markDrawService.CurrentMarkDrawType == SegToolsEnum.Erase
                || _markDrawService.CurrentMarkDrawType == SegToolsEnum.MarkNone)
                return;

            if (p.X < 0 || p.X > 1024 || p.Y < 0 || p.Y > 1024) return;

            // 计算点的坐标
            var rsP = CalcPoint(p);
            if (rsP.All(i => i == -1)) return;

            // 触发十字线
            if (_markDrawService.CurrentMarkDrawType == SegToolsEnum.CrossLine)
            {
                await CrossLineInteraction!.Handle(rsP);
                return;
            }

            // 以下是标记点
            var point = _markDrawService.MarkPoint(rsP);
            await _imageShowService.FrushAllOrientationMats(point);
        });

        // 鼠标滚轮事件， 图像翻页
        MouseWheelUpdateCurrentIndexCommand = ReactiveCommand.CreateFromTask<int>(async index =>
        {
            switch (index)
            {
                case < 0:
                    CurrentIndex++;
                    break;
                case > 0:
                    CurrentIndex--;
                    break;
            }

            if (CurrentIndex < 0) CurrentIndex = 0;
            if (CurrentIndex > Count) CurrentIndex = Count;
            await _imageShowService.FrushMats(CurrentIndex, _currentImageOrientation);
        });

        _imageShowService.FrushMatsEvent += FrushMatsHandler;
        _imageShowService.WindowAdjustChangeEvent += WindowAdjustChangeHandler;
        _imageShowService.FrushTagMatEvent += FrushTagMatHandler;
    }

    public void SetImageOrientation(ImageOrientationEnum orientation)
    {
        _currentImageOrientation = orientation;
    }

    /// <summary>
    /// 窗款窗位置调整
    /// </summary>
    /// <param name="obj"></param>
    void WindowAdjustChangeHandler(object obj)
    {
        _imageShowService.FrushMats(CurrentIndex, _currentImageOrientation);
    }

    void FrushMatsHandler(FrushMats mats)
    {
        if (mats.Orientation != _currentImageOrientation) return;

        RxApp.MainThreadScheduler.Schedule(() =>
        {
            _noFrush = true;

            OriginMat = mats.CtImage;
            LableMat = mats.LableMat;
            //RadiusMat = mats.RADIUSMat;
            //TfccMat = mats.TFCCMat;
            //UlnaMat = mats.ULNAMat;
            
            if (CurrentIndex != mats.CurrentIndex && mats.CurrentIndex != -1) CurrentIndex = mats.CurrentIndex;
            if (Count != mats.Count && mats.Count != -1) Count = mats.Count;

            MarkMat = _markDrawService.GetMarkMat(CurrentIndex, _currentImageOrientation);

            _noFrush = false;
        });
    }

    /// <summary>
    /// 刷新tag图像
    /// </summary>
    /// <param name="tagMat"></param>
    void FrushTagMatHandler(Mat tagMat)
    {
        RxApp.MainThreadScheduler.Schedule(() =>
        {
            TagMat = tagMat;
        });
    }

    /// <summary>
    /// 坐标点的计算，涉及十字线 标记点
    /// </summary>
    /// <param name="p"></param>
    /// <returns></returns>
    double[] CalcPoint(Point p, bool isDraw = false)
    {
        // 计算点的坐标
        var newPoint = ImageHelper.ConvertPoint2d(new Point2d(p.X, p.Y), new Size(1024.0, 1024.0),
            OriginMat!.Size());
        if (newPoint[0] > OriginMat.Width || newPoint[0] < 0 || newPoint[1] > OriginMat.Height ||
            newPoint[1] < 0) return new double[] { -1,-1,-1};

        var rsP = new double[3];
        switch (_currentImageOrientation)
        {
            case ImageOrientationEnum.TransversePlane:
                rsP = new double[] { newPoint[0], newPoint[1], CurrentIndex };
                break;
            case ImageOrientationEnum.SagittalPlane:
                rsP = new double[] { CurrentIndex, newPoint[0], newPoint[1] / (isDraw ? 1 : AppServiceEnv.ImageInfo.ImageFactor) };
                break;
            case ImageOrientationEnum.CoronalPlane:
                rsP = new double[] { newPoint[0], CurrentIndex, newPoint[1] / (isDraw ? 1 : AppServiceEnv.ImageInfo.ImageFactor) };
                break;
        }

        return rsP;
    }

}
